﻿using Autodesk.Revit.DB;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FloatDemo.Methods
{
    public static class CurveMethodEx
    {
        /// <summary>
        /// 设置线段Z值
        /// </summary>
        /// <param name="curve"></param>
        /// <param name="z"></param>
        /// <returns></returns>
        public static Curve SetZ(this Curve curve, double z)
        {
            if (curve is Line line)
            {
                var start = line.GetEndPoint(0);
                var end = line.GetEndPoint(1);
                var newStart = new XYZ(start.X, start.Y, z);
                var newEnd = new XYZ(end.X, end.Y, z);
                if ((newStart - newEnd).GetLength() > 0.0027)
                {
                    return Line.CreateBound(newStart, newEnd);
                }
            }
            else if (curve is Arc arc)
            {
                if (arc.IsCircle())
                {
                    XYZ center = arc.Center.SetZ(z);
                    return Arc.Create(center, arc.Radius, 0, Math.PI * 2, arc.XDirection, arc.YDirection);
                }
                else
                {
                    return Arc.Create(arc.GetEndPoint(0).SetZ(z), arc.GetEndPoint(1).SetZ(z), arc.Evaluate(0.5, true).SetZ(z));
                }
            }
            return curve;
        }
        /// <summary>
        /// 是圆？？？
        /// </summary>
        /// <param name="arc"></param>
        /// <returns></returns>
        public static bool IsCircle(this Arc arc)
        {
            return arc.Length.IsAlmostEqual(arc.Radius * 2 * Math.PI, 1 / 304.8);
        }
        /// <summary>
        /// 修改Z轴
        /// </summary>
        /// <param name="xyz"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static XYZ SetZ(this XYZ xyz, double value = 0)
        {
            return new XYZ(xyz.X, xyz.Y, value);
        }

        /// <summary>
        /// 修改y轴
        /// </summary>
        /// <param name="xyz"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static XYZ SetY(this XYZ xyz, double value = 0)
        {
            return new XYZ(xyz.X, value, xyz.Z);
        }

        /// <summary>
        /// 点转换
        /// </summary>
        /// <param name="point"></param>
        /// <param name="transform"></param>
        /// <returns></returns>
        public static XYZ OfPoint(this XYZ point, Transform transform)
        {
            return transform.OfPoint(point);
        }
        /// <summary>
        /// 是否相等
        /// </summary>
        /// <param name="d1"></param>
        /// <param name="d2"></param>
        /// <param name="tor"></param>
        /// <returns></returns>
        public static bool IsAlmostEqual(this double d1, double d2, double tor = 0.001)
        {
            return Math.Abs(d1 - d2) < tor;
        }
        /// <summary>
        /// 获取点到线上的投影点
        /// </summary>
        /// <param name="l"></param>
        /// <param name="p"></param>
        /// <returns></returns>
        public static XYZ GetProjectPoint(this Line l, XYZ p)
        {
            Line line = Line.CreateBound(l.GetEndPoint(0), l.GetEndPoint(1));
            line.MakeUnbound();
            return line.Project(p).XYZPoint;
        }
        /// <summary>
        /// 点是否能投影到线上，使用前确保点和线在同一个平面
        /// </summary>
        /// <param name="line"></param>
        /// <param name="point"></param>
        /// <param name="tolerance"></param>
        /// <returns></returns>
        public static bool CanProject(this Line line, XYZ point, double tolerance = 0.001)
        {
            var dirt = line.Direction;
            if (point.DotProduct(dirt).IsBetween(line.GetEndPoint(0).DotProduct(dirt), line.GetEndPoint(1).DotProduct(dirt), true, true, tolerance))
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        /// <summary>
        /// 是否介于最大值和最小值之间
        /// </summary>
        /// <param name="d">用于比较的数值</param>
        /// <param name="minValue">最小值</param>
        /// <param name="maxValue">最大值</param>
        /// <param name="isLeftEqual">是否可以等于最小值</param>
        /// <param name="isRightEqual">是否可以等于最大值</param>
        /// <param name="tolerance">容差</param>
        /// <returns></returns>
        public static bool IsBetween(this double d, double minValue, double maxValue, bool isLeftEqual = false, bool isRightEqual = false, double tolerance = 0.001)
        {
            //左等号
            if (isLeftEqual && d.IsAlmostEqual(minValue, tolerance))
                return true;
            //右等号
            if (isLeftEqual && d.IsAlmostEqual(maxValue, tolerance))
                return true;
            if (d - minValue > 0.0001 && maxValue - d > 0.0001)
                return true;
            return false;
        }
    }
}
